
#include"cmd.h"



extern MEMORY_MANAGEMENT * memman ;
extern struct FILEINFO *finfo ;
extern int * fat12 ;

void cmd_init (CMD * cmd) { 
	strcpy (cmd->head ,"pancake os >");
	//cmd->head =  
	cmd->first = 8+ strlen(cmd->head)*8 ;
	cmd->cursor_x = cmd->first;
	cmd->cursor_y = 28 ;
	cmd->cursor_color = COL8_000000 ;

	cmd->length = 0 ;

}
//没有head ，并且光标为黑色
void cmd_init_nohead (CMD * cmd) { 
	
	
	cmd->first = 8 ;
	cmd->cursor_x = cmd->first;
	cmd->cursor_y = 28 ;
	cmd->cursor_color = COL8_FFFFFF ;

	cmd->length = 0 ;
}

//换行 普通换行和滚动换行
void cmd_newline (CMD * cmd ,int hashead ) { //addhead 判断是否加上head 
	int x,y ;
	SHEET * sht_window = cmd->sheet ;

	putchars8_sht ( cmd->sheet,cmd->cursor_x ,cmd->cursor_y ,COL8_FFFFFF, COL8_000000 , " ",1);  //清除闪烁的cursor  

	if (cmd->cursor_y < sht_window->bysize-40){ //bysize-8是最后一行  
		cmd->cursor_y += 16;	
	}else { 
		for (y = 28 ; y < sht_window->bysize-9-16; y++) { 
			for (x = 8 ; x< sht_window->bxsize-8 ;x++ ) { 
				sht_window->buf[x+y*sht_window->bxsize] = sht_window->buf[x+(y+16)*sht_window->bxsize] ;
			}
		}
		for (y =sht_window->bysize-34; y <sht_window->bysize-8 ; y++){ //最后一行涂黑
			for (x = 8 ; x < sht_window->bxsize-8 ;x ++) { 
				sht_window->buf[x+y* sht_window->bxsize] = COL8_000000 ;
			}
		}
		
		sheet_refresh_bysht2 (sht_window,8 ,28 ,sht_window->bxsize-9 ,sht_window->bysize-9) ;
	}
	if (hashead) { 
		cmd->cursor_x = cmd->first;
		putchars8_sht ( cmd->sheet,8 ,cmd->cursor_y ,COL8_FFFFFF, COL8_000000 , cmd->head,strlen(cmd->head));  //
	}else { 
		cmd->cursor_x = 8 ;
	}
	
	//return cursor_y ; 
}   

/** 打印单个字符
	@ch  : 输出的字符
	@move :表示光标是否移动 
*/
void cmd_putchar (CMD * cmd ,char ch ,char move ) { 
	char s[2]  ; 
	s[0] = ch ;
	s[1] = '\0' ;

	if (s[0]=='\n') { 
		cmd_newline(cmd,0);
	}else {
		putchars8_sht ( cmd->sheet,cmd->cursor_x ,cmd->cursor_y ,COL8_FFFFFF, COL8_000000 ,s,1); 
		if (move ){
			cmd->cursor_x +=8 ;
			if (cmd->cursor_x >=cmd->sheet->bxsize -16) { 
				cmd_newline (cmd ,0);
			}
		}
	}

	
}

void cmd_putchar2 (CMD * cmd ,char ch ,char move ) { 
	char s[2]  ; 
	s[0] = ch ;
	s[1] = '\0' ;

	if (s[0]=='\n') { 
		cmd_newline(cmd,0);
	}else {
		putchars8_sht ( cmd->sheet,cmd->cursor_x ,cmd->cursor_y ,COL8_000000, COL8_FFFFFF ,s,1); 
		if (move ){
			cmd->cursor_x +=8 ;
			if (cmd->cursor_x >=cmd->sheet->bxsize -16) { 
				cmd_newline (cmd ,0);
			}
		}
	}

	
}


void cmd_putcmdchar (CMD * cmd ,char ch ,char move) { 
	cmd_putchar (cmd,ch,move);
	cmd->cmdline[cmd->length] = ch ;
	cmd->length ++ ;
}


//输出一串字符串
void cmd_putchars (CMD * cmd ,char * s){ 
	int i ,len= strlen (s) ;
	for (i = 0 ; i < len ; i ++) { 
		cmd_putchar (cmd ,s[i] ,1);
	}
	return  ;

}
//输出一串字符串
void cmd_putchars_length (CMD * cmd ,char * s ,int len){ 
	int i ;
	for (i = 0 ; i < len ; i ++) { 
		cmd_putchar (cmd ,s[i] ,1);
	}
	return  ;
}


int cmd_exec (CMD * cmd) { 
	char str[40] ;
	int i ,j=0,var=0 ,error=0,flag = 0 ;  //flag用于字符串解析 ，出现第一个非空字符时设置为1 ，用于解析出命令

	TASK * task_n ; 
	CMD * cmd2 ;
	//char command[10][10]; //解析出命令
	cmd->cmdline[cmd->length] ='\0';
	if (cmd->length ==0) { 
		cmd_newline(cmd ,1);
		return -1;
	}
	cmd->args_length = str_split (cmd->cmdline ,cmd->args,' ');
/*
	for (i = 0 ; i < cmd->args_length ;i ++) { 
		cmd_newline (cmd ,0);
		putchars8_sht ( cmd->sheet,16 ,cmd->cursor_y ,COL8_FFFFFF, COL8_000000 , cmd->args[i],strlen(cmd->args[i]));  //
		
	}
	cmd_newline (cmd ,0);
	sprintf(str,"count =   %2d" ,cmd->args_length);
	putchars8_sht ( cmd->sheet,16 ,cmd->cursor_y ,COL8_FFFFFF, COL8_000000 , str,strlen(str));  //
	cmd_newline(cmd ,0);
*/
	if (strcmp (cmd->args[0],"cls") ==0 ){ 
		 cmd_cls (cmd);
		 putchars8_sht ( cmd->sheet,8 ,cmd->cursor_y ,COL8_FFFFFF, COL8_000000 , cmd->head,strlen(cmd->head));  //画str字符串
		 
	}
	else if (strcmp (cmd->args[0],"mem") ==0) { 
		cmd_mem (cmd);
	}
	else if (strcmp (cmd->args[0],"ls") ==0) { 
		cmd_ls(cmd);
	}
	else if (strcmp (cmd->args[0],"cat") ==0) { 
		cmd_cat(cmd);
	}
	else if (strcmp (cmd->args[0],"c") ==0) {  //关闭窗口
		 task_n = task_now () ;
		 if (task_n->cmd !=0  ) { 
		 	cmd2 =(CMD *) task_n->cmd  ;
		 	sheet_free (cmd2->sheet);
		 	//memman_free_4k (cmd,sizeof(CMD)) ;
		 }
		 cmd_putchars (cmd,"\n\n window was closed ....\n");
		 cmd_newline (cmd,1);
	}
	else { 
		 cmd_run_app (cmd);

		
	}
	for (i=0 ;i <cmd->length ;i++) { //把所有字符都清空，否则只把第一个字符置为\0，在下次输入字符以后\0被覆盖，字符串又回到原来的样子了
		cmd->cmdline[i] ='\0' ;
	} 
	cmd->length = 0 ;//清空cmdline[]
	for (i =0 ; i<cmd->args_length ;i++) { 
		var = strlen (cmd->args[i]) ;
		for (j=0 ;j <var ;j++) { 
			cmd->args[i][j] = 0 ;
		}
	}
	cmd->args_length = 0 ;
	
	return 0 ;
}

int cmd_mem(CMD * cmd){ 
	char s[100];
	unsigned int free_total  ,total;
	
	total = memman->totalsize>>20 ;  //总MB
	free_total = memman_free_total (memman) >>10; //剩余 KB
	
	cmd_newline (cmd ,0);
	sprintf(s,"total size ------------ %d MB",total);
	putchars8_sht ( cmd->sheet,16 ,cmd->cursor_y ,COL8_FFFFFF, COL8_000000 , s,strlen(s));  //画str字符串
	cmd_newline (cmd ,0);
	sprintf(s,"free size  ------------ %d KB",free_total);
	putchars8_sht ( cmd->sheet,16 ,cmd->cursor_y ,COL8_FFFFFF, COL8_000000 , s,strlen(s));  //画str字符串
	cmd_newline (cmd ,1);

} 


int cmd_cls (CMD * cmd){ 
	SHEET * sht_window =  cmd->sheet ;
	int x ,y  ;
	for (y = 28 ; y < sht_window->bysize-8; y++) { 
		for (x = 8 ; x<sht_window->bxsize-8 ;x++) { 
			sht_window->buf[x+ y*sht_window->bxsize] = COL8_000000 ;
		}
	}
	cmd->cursor_x = cmd->first ;
	cmd->cursor_y = 28 ;
	sheet_refresh_bysht2 (sht_window,8 ,28 ,sht_window->bxsize-9 ,sht_window->bysize-9) ; 


	return  0 ; 
}   

int cmd_ls(CMD * cmd) { 
	int i ,j;
	char s[30] ;

	cmd_newline (cmd ,0);
	for (i = 0 ; i < 224 ;i ++) { 
		if (finfo[i].name[0] ==0x00){  //不包含任何文件信息
			break ;
		}
		if (finfo[i].name[0] !=0xe5) {  //文件已经被删除
			sprintf (s,"filename.ext       %7d B",finfo[i].size);
			for (j = 0 ; j < 8 ;j++) { 
				s[j] = finfo[i].name[j] ;
			}
			//s[8]是 '.'
			s[9] = finfo[i].ext[0];
			s[10] = finfo[i].ext[1];
			s[11] = finfo[i].ext[2];
			putchars8_sht ( cmd->sheet,16 ,cmd->cursor_y ,COL8_FFFFFF, COL8_000000 , s,strlen(s));  //
			cmd_newline (cmd ,0);
		}
	}
	cmd_newline (cmd ,1);
}
int cmd_cat (CMD * cmd) {
	int length ,i;
	struct FILEINFO  *f = 0 ;
	char *  p ,s[2];
	if (cmd->args_length <2) { 
		cmd_newline (cmd ,1);
		return 1;
	}
	cmd_newline (cmd ,0);
	f = file_search (cmd->args[1]) ; //查询该文件
	if (f != 0 ){ 
		p = memman_alloc_4k(memman,f->size ); //分配和文件大小一样大的内存 

		file_loadfile (f,fat12, ADR_DISKIMG +0x003e00 ,p) ;
		for (i = 0 ; i < f->size ;i++) { 
			s[0] = p[i] ;
			s[1] = 0 ;

			if (s[0] ==0x09) {//制表符
				putchars8_sht ( cmd->sheet,cmd->cursor_x ,cmd->cursor_y ,COL8_FFFFFF, COL8_000000 ," ",1);  //
				/*
				for (;;){
					putchars8_sht ( cmd->sheet,cmd->cursor_x ,cmd->cursor_y ,COL8_FFFFFF, COL8_000000 ," ",1);  //
					cmd->cursor_x +=8 ;
					if (cmd->cursor_x >= cmd->sheet->bxsize - 16) { 
						cmd_newline (cmd,0);
					}
					if ((cmd->cursor_x -8)&0x1f ==0) { 
						break ; //被32整除则break ; ,一个制表符表示1-4格
					}
				} */
			}
			else if (s[0] ==0x0a) {   // 实际上0x0a + 0x0d 为回车换行 ，但我们现在为了方便 只处理0x0a 
				cmd_newline (cmd,0);
				
			}
			else if (s[0] ==0x0d) { 
				
			}
			else {  //写字符
				putchars8_sht ( cmd->sheet,cmd->cursor_x ,cmd->cursor_y ,COL8_FFFFFF, COL8_000000 ,s,1);  //
				cmd->cursor_x +=8 ;
				if (cmd->cursor_x >= cmd->sheet->bxsize - 16) { 
					cmd_newline (cmd,0);
				}
			}
		}
		// 读取
		//putchars8_sht ( cmd->sheet,16 ,cmd->cursor_y ,COL8_FFFFFF, COL8_000000 , " has this file",30);  //
	}else { 
		putchars8_sht ( cmd->sheet,16,cmd->cursor_y ,COL8_FFFFFF, COL8_000000 , "no file found ",30);  //
		cmd_newline(cmd ,0);
	}
	cmd_newline(cmd ,1);
	return 0 ;
}


void cmd_run_app (CMD  * cmd ) { 
	SEGMENT_DESCRIPTOR *gdt = ( SEGMENT_DESCRIPTOR *) ADR_GDT;
	int length ,i;
	struct FILEINFO  *f = 0 ;
	char *  p ,*q;
	int segsiz ,esp,datsiz,dathrb ; //文件的属性
	TASK * task_n = task_now () ;
	char name [15] ;
	

	cmd_newline (cmd ,0);

	//如果没有后缀，自动加上后缀.hrb
	strcpy (name,cmd->args[0]);

	if (str_strchr(name,'.') == -1 ){ 
		strcat(name,".hrb");
	}



	f = file_search (name) ; //查询该文件
	if (f != 0 ){ 
		p = memman_alloc_4k(memman,f->size ); //分配和文件大小一样大的内存 用做代码段
		file_loadfile (f,fat12, ADR_DISKIMG +0x003e00 ,p) ;
	//	cmd_putchars_length(cmd,p + 4,4) ;
		if (f->size >= 8 && strncmp(p + 4, "Hari", 4) == 0) {  //修改hrb文件，相当于执行call 0x1b  (ox1b 为HariMain的地址)
			segsiz = *((int *)(p+ 0x0000));
			esp = *((int *)(p+ 0x000c));
			datsiz = *((int *)(p+ 0x0010));
			dathrb = *((int *)(p+ 0x0014));
			q = memman_alloc_4k(memman,segsiz ); //分配segsiz K 用作数据段
			*((int *)0x0fe8) =(int)q ;
			set_segmdesc(task_n->ldt+0, f->size-1, (int )p, AR_CODE32_ER + 0x60); //设置该app的段址(3-1002为任务调度段)   代码段为ldt[0] ,数据段为ldt[1]  
			set_segmdesc(task_n->ldt+1, segsiz-1, (int )q, AR_DATA32_RW + 0x60); // + 0x60的目的是设置该段为应用程序用 ，这样cpu提供的保护机制使程序不能再修改cs,ds，调用farcall ,farjmp 
			
			for (i = 0 ; i < datsiz ;i++) { 
				q[esp+i] = p[dathrb +i] ; //代码段p 中包
			}
			start_app(0x1b, 0*8+4, esp, 1*8+4 ,& (task_n->tss.esp0));  // + 4表示该段为ldt段  因为第3位为1时表示该地址为ldt地址 ，为0表示gdt地址

			//关闭未关闭的文件
			for (i = 0 ; i < 8 ; i ++) {
				if (task_n->fhandler[i].buf != 0) { 
					memman_free_4k(memman,task_n->fhandler[i].buf,task_n->fhandler[i].size);
					task_n->fhandler[i].buf = 0 ;
				}
			}


			memman_free_4k(memman,q,segsiz );
		}else {

			cmd_putchars(cmd," file format error ...") ;
			//cmd_newline (cmd,1);
			//start_app(0, 1003 * 8, 64 * 1024, 1004 * 8 ,& (task_n->tss.esp0));
		}
		//farcall (0 ,1003*8) ;

		memman_free_4k(memman,p,f->size );
		
		cmd_newline (cmd ,1);

	}else { 
		cmd_warnning (cmd,"no command or executable file found ");
	}
	
}



int cmd_warnning (CMD * cmd ,char str []) { 
	cmd_newline (cmd ,0);
	putchars8_sht ( cmd->sheet,16 ,cmd->cursor_y ,COL8_FFFFFF, COL8_000000 , str,strlen(str));  //
	cmd_newline(cmd ,0);
	cmd_newline(cmd ,1);
}



int api_main(int edi ,int esi ,int ebp ,int esp ,int ebx ,int edx ,int ecx ,int eax) { 
	int i ; 
	CMD * cmd = (CMD *) *((int *) 0x0fec) ;

	CMD * win_cmd  ;
	CMD * cmd_var ;

	TASK * task_n = task_now ();
	int ds_base =  *((int *) 0x0fe8) ; //数据段基址
	char s[10];
	SHEET_MANAGEMENT * sht_man = (SHEET_MANAGEMENT *) (*(int *)0x0fe4 ) ;
	SHEET * sht_window ;
	FILE_HANDLER * fh  ;
	struct FILEINFO * finfo ;

	int *reg = &eax +1 ; //eax栈地址后面的值 (第二次pushad 的一系列寄存器值) 
			/*强行改写了pushad保存的值
		reg[0] : edi ,reg[1] :esi , reg[2] :ebp , reg[3] :esp 
		reg[4] : ebx ,reg[5] :edx , reg[6] :ecx , reg[7] :eax
	
			*/ 

	//buf_sht_window= (unsigned char *) memman_alloc_4k(memman, 160 * 52);

	switch (edx) { 
		case 1 :
		 	cmd_putchar (cmd,eax & 0xff ,1) ;
		 break ;
		case 2 :
			//sprintf (s,"%08X",ebx);
			//cmd_putchars(cmd,s);
			cmd_putchars(cmd,(char*) ebx+ds_base);
		 break ;
		case 3 :
			cmd_putchars_length(cmd,(char*) ebx+ds_base , ecx);
		 break ;
		case 4 :
			return &(task_n->tss.esp0); 
		case 5 :

			win_cmd = memman_alloc_4k (memman,sizeof (CMD)) ;
			cmd_init_nohead(win_cmd);			

			sht_window = sheet_alloc (sht_man);
			win_cmd->sheet = sht_window ;

			sheet_setbuf (sht_window,(char *)ebx+ds_base,esi,edi,eax) ;
			make_window8((char *)ebx+ds_base, esi, edi, (char *)ecx+ds_base ,1) ;
			make_textbox8(sht_window, 8, 28, esi-16,edi-36, COL8_FFFFFF);
			
			sheet_slide (sht_window,200,180);
			sheet_updown (sht_window,4);
			reg[7] = (int) win_cmd ;
			
			task_n->cmd = (int)win_cmd ;

			

			break ;
		case 6 : //void _api_putchar2win(int cmd_win , int c);
			cmd_var = (CMD *) ((char *)ebx) ;
			cmd_putchar2 (cmd_var,eax & 0xff ,1) ;
		case 21 : //int api_fopen (char * name)
			for (i =0 ; i< 8 ; i++) { 
				if (task_n->fhandler[i].buf ==0){ 
					break; 
				}
			}
			reg[7] = 0 ;

			if (i< 8) { 
				
				finfo = file_search ((char *)ebx +ds_base) ; //查询该文件
				if (finfo != 0 ){ 
					fh = &task_n->fhandler[i] ;
					reg[7] = fh ;
					fh->buf = memman_alloc_4k(memman,finfo->size ); 
					fh->size = finfo->size ;
					fh->pos = 0 ; 
					file_loadfile (finfo,task_n->fat, ADR_DISKIMG +0x003e00 ,fh->buf) ;
				}
			}

			break ;
		case 22:   //void api_fclose (int fhandler) 
			fh = (FILE_HANDLER *) eax ;
			memman_free_4k(memman,fh->buf,fh->size);
			break;
		case 23:   //void api_fseek (int fhandler ,int offset ,int mode) ;
			break ;
		case 24 :   //int api_fread (char *buf ,int maxsize ,int fhandler) ;
			fh = (FILE_HANDLER *) eax ;
			for (i = 0 ; i< ecx ; i++){ 
				if (fh->pos >=fh->size ){ 
					break ;
				}
				*((char *)ebx +ds_base +i ) = fh->buf[fh->pos] ;
				fh->pos ++ ; 
			}
			reg[7] = i ;
			break ;
		case 25 :  //int api_fsize (int fhandler ,int mode) ;
			fh = (FILE_HANDLER *) eax ;
			if (ecx ==0) { 
				reg[7] = fh->size ;
			}
			else if (ecx==1) { 
				reg[7] ==fh->pos ;
			}
			else if (ecx ==2) { 
				reg[7] = fh->pos - fh->size ;
			}

			break;
		case 30 :  //int api_cmdline (char * buf ,int length ) ;
			for (i =0 ;i<cmd->length;i++) {
				if (i >=ecx-1) { 
					break ;
				}
				*((char *)ebx +ds_base +i) = cmd->cmdline[i] ;

			}
			*((char *)ebx +ds_base +i) = '\0' ;			
			reg[7] = i ;
			break;

	}
	return 0;
}